﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MongoDB.Bson;
using WanPiJie.Products;
using System.Reflection;

namespace WanPiJie
{
	/// <summary>
	/// 提供指定类的扩展功能
	/// </summary>
	public static class ClassExtension
    {
        #region 对于Commodity类功能的扩展

        /// <summary>
		/// 将商品销售信息转为Bson文档格式
		/// </summary>
		/// <param name="_this">商品销售信息</param>
		/// <returns>Bson文档化的商品销售信息</returns>
		public static BsonDocument ToBsonDocument(this Commodity _this)
		{
			return new BsonDocument() {
			{"UpdateTime",DateTime.Now},
			{"AddTime",DateTime.Now},
			{"CatalogId",_this.CatalogId},
			{"ProductId",_this.ProductId},
			{"Title",_this.Title},
			{"_id",_this.SerialNumber},
			{"Attributes", ConvertAttributesToBson(_this)},
			{"Volume",_this.Volume},
			{"MaxAge",_this.MaxAge},
			{"MinAge",_this.MinAge},
			{"MaxWeight",_this.MaxWeight},
			{"MinWeight",_this.MinWeight},
			{"Picture",_this.Picture},
			{"Location",_this.Location},
			{"ShopUrl",_this.ShopUrl},
			{"SellerCreditScore",_this.SellerCreditScore},
			{"SellerNick",_this.SellerNick},
			{"Url",_this.Url},
			{"Price",_this.Price.ToString()}
			};
		}

		/// <summary>
		/// 将商品销售信息属性转换为Bson文档结构
		/// </summary>
		/// <param name="_this">商品销售信息</param>
		/// <returns></returns>
		public static BsonDocument ConvertAttributesToBson(this Commodity _this)
		{
			BsonDocument attributes = new BsonDocument();
			foreach (var key in _this.Attributes.Keys)
			{
				if (attributes.Contains(key.ToString()))
				{
					if (attributes[key.ToString()].IsBsonArray)
					{
						attributes.Set(key.ToString(), attributes[key.ToString()].AsBsonArray.Add(_this.Attributes[key]));
					}
					else
					{
						BsonArray array = new BsonArray();
						array.Add(attributes[key.ToString()]);
						array.Add(_this.Attributes[key]);
						attributes.Set(key.ToString(), array);
					}
				}
				else
				{
					attributes.Add(new BsonElement(key.ToString(), _this.Attributes[key]));
				}
			}
			return attributes;
		}
		#endregion

		#region 对Product功能的扩展

		/// <summary>
		///将单品对象转换为Bson文档对象
		/// </summary>
		/// <param name="_this">单品对象</param>
		/// <returns>Bson文档对象</returns>
		public static BsonDocument ToBsonDocument(this Product _this)
		{
			string key;
			object value;
			ComplexAttributeValue attributeValue;
			BsonDocument bsonDocument = new BsonDocument();
			var properties = typeof(Product).GetProperties(BindingFlags.Public | BindingFlags.Instance);
			foreach (var p in properties)
			{
				key = p.Name.Equals("SerialNumber") ? "_id" : p.Name;
				value = p.GetValue(_this, null);
				if (value != null)
				{
					attributeValue = value as ComplexAttributeValue;
					if (attributeValue != null)
					{
						bsonDocument.Add(key, attributeValue.ToBsonDocument());
					}
					else
					{
						bsonDocument.Add(new Dictionary<string, object> { { key, value } });
					}
				}
			}
			return bsonDocument;
		}

		#endregion

		#region 对于BsonDocument类功能的扩展

		/// <summary>
		///将Bson对象转换为商品销售信息
		/// </summary>
		/// <param name="_this">bson格式的商品销售信息对象</param>
		/// <returns>对应的商品销售信息对象</returns>
		public static Commodity ToCommodity(this	BsonDocument _this)
		{
			if (_this == null)
			{
				return null;
			}
			Commodity commodity = new Commodity
			{
				Picture = _this["Picture"].AsString,
				AddTime = _this["AddTime"].AsDateTime,
				CatalogId = _this["CatalogId"].AsInt64,
				Url = _this["Url"].AsString,
				Title = _this["Title"].AsString,
				Price = decimal.Parse(_this["Price"].AsString),
				MinWeight = _this["MinWeight"].AsInt32,
				MaxWeight = _this["MaxWeight"].AsInt32,
				MinAge = _this["MinAge"].AsInt32,
				MaxAge = _this["MaxAge"].AsInt32,
				SerialNumber = _this["_id"].AsInt64,
				ProductId = _this["ProductId"].AsInt64,
				Volume = _this["Volume"].AsInt32,
				UpdateTime = _this["UpdateTime"].AsDateTime,
				Location = _this["Location"].AsString,
				ShopUrl = _this["ShopUrl"].AsString,
				SellerCreditScore = _this["SellerCreditScore"].AsInt32,
				SellerNick = _this["SellerNick"].AsString,
				Attributes = new Dictionary<long, string>()
			};

			foreach (var attributeValue in _this["Attributes"].AsBsonDocument)
			{
				commodity.Attributes.Add(long.Parse(attributeValue.Name), attributeValue.Value.AsString);
			}
			return commodity;
		}

		/// <summary>
		/// 将MongoDB中的数据转为单品对象
		/// </summary>
		/// <param name="_this">当前Bson文档对象</param>
		/// <returns>单品业务对象</returns>
		public static Product ToProduct(this	BsonDocument _this)
		{
			if (_this == null)
			{
				return null;
			}
			Product singleProduct = new Product();
			string key;
			BsonValue value;
			var properties = typeof(Product).GetProperties(BindingFlags.Public | BindingFlags.Instance);
			foreach (var p in properties)
			{
				key = p.Name.Equals("SerialNumber") ? "_id" : p.Name;
				try
				{
					value = _this[key];
					if (value.IsInt64)
					{
						p.SetValue(singleProduct, value.AsInt64, null);
					}
					else if (value.IsBsonDocument)
					{
						p.SetValue(singleProduct, value.AsBsonDocument.ToComplexAttributeValue(), null);
					}
				}
				catch (KeyNotFoundException)
				{
					p.SetValue(singleProduct, null, null);
				}
			}
			return singleProduct;
		}

		/// <summary>
		///将BsonDocument对象转为ComplexAttributeValue对象
		/// </summary>
		/// <param name="_this">BsonDocument</param>
		/// <returns>对应的ComplexAttributeValue对象</returns>
		public static ComplexAttributeValue ToComplexAttributeValue(this	BsonDocument _this)
		{
			return _this != null ? new ComplexAttributeValue
			{
				SerialNumber = _this["SerialNumber"].AsInt64,
				Value = _this["Value"].AsString,
				ValueSerialNumber = _this["ValueSerialNumber"].AsInt64
			} : null;
		}

		#endregion

		#region 对于ComplexAttributeValue的扩展

		/// <summary>
		/// 将ComplexAttributeValue装换为BsonDocument
		/// </summary>
		/// <param name="_this">当前ComplexAttributeValue对象</param>
		/// <returns>对应的BsonDocument对象</returns>
		public static BsonDocument ToBsonDocument(this	ComplexAttributeValue _this)
		{
			return _this != null ? new BsonDocument{
				{"SerialNumber",_this.SerialNumber},
				{"Value",_this.Value},
				{"ValueSerialNumber",_this.ValueSerialNumber}
			} : null;
		}

		#endregion
	}
}
